/* p8_3.c: Using SSI1 to connect to LTC1661 DAC */
/* Generate sine wave on output B */
/* floating point processor is enabled to generate waveform data array */

#include "TM4C123GH6PM.h"
#include <math.h>

#define WAVEFORM_LENGTH 1024
int sinewave[WAVEFORM_LENGTH];

void init_SSI1(void);
void LTC1661Write(int chan, short d);

int main(void)
{
    int i;
    float fRadians;
#ifndef M_PI
    float M_PI = 4 * atan(1.0);
#endif    

    init_SSI1();
    
    /* construct data table for a sine wave */
    fRadians = ((2 * M_PI) / WAVEFORM_LENGTH);
    for (i = 0; i < WAVEFORM_LENGTH; i++)
    {
        sinewave[i] = (short)(511 * (sinf(fRadians * i) + 1));
    }
    
    for(;;)
    {
        for (i = 0; i < WAVEFORM_LENGTH; i++)
        {
            /* write a sine wave to channel B */
            LTC1661Write(1, sinewave[i]);   
        }
    }
}

void LTC1661Write(int chan, short data)
{
    GPIOF->DATA &= ~0x04;       /* assert SS low */
    data = (data & 0x03FF) << 2; /* bit 1-0 unused */
    if (chan == 0)              /* add control code with channel number */
        data |= 0x9000;
    else
        data |= 0xA000;
    while((SSI1->SR & 2) == 0); /* wait until FIFO not full */
    SSI1->DR = data >> 8;       /* transmit high byte */
    while((SSI1->SR & 2) == 0); /* wait until FIFO not full */
    SSI1->DR = data & 0xFF;     /* transmit low byte */
    while(SSI1->SR & 0x10);     /* wait until transmit complete */
    GPIOF->DATA |= 0x04;        /* keep SS idle high */
}

void init_SSI1(void)
{
    SYSCTL->RCGCSSI |= 2;       /* enable clock to SSI1 */
    SYSCTL->RCGCGPIO |= 8;      /* enable clock to GPIOD for SSI1 */
    SYSCTL->RCGCGPIO |= 0x20;   /* enable clock to GPIOF for slave select */

    /* configure PORTD 3, 1 for SSI1 clock and Tx */
    GPIOD->AMSEL &= ~0x09;      /* disable analog for these pins */
    GPIOD->DEN |= 0x09;         /* and make them digital */
    GPIOD->AFSEL |= 0x09;       /* enable alternate function */
    GPIOD->PCTL &= ~0x0000F00F; /* assign pins to SSI1 */
    GPIOD->PCTL |= 0x00002002;  /* assign pins to SSI1 */
    
    /* configure PORTF 2 for slave select */
    GPIOF->DEN |= 0x04;         /* make the pin digital */
    GPIOF->DIR |= 0x04;         /* make the pin output */
    GPIOF->DATA |= 0x04;        /* keep SS idle high */

    /* SPI Master, POL = 0, PHA = 0, clock = 4 MHz, 16 bit data */
    SSI1->CR1 = 0;          /* disable SSI and make it master */
    SSI1->CC = 0;           /* use system clock */
    SSI1->CPSR = 2;         /* prescaler divided by 2 */
    SSI1->CR0 = 0x0007;     /* 8 MHz SSI clock, SPI mode, 8 bit data */
    SSI1->CR1 |= 2;         /* enable SSI1 */
}

void SystemInit(void)
{
    /* Grant coprocessor access */
    /* This is required since TM4C123G has a floating point coprocessor */
    SCB->CPACR |= 0x00f00000;
}